Imports System.Runtime.Serialization

<Serializable(), ObfuscationAttribute(Exclude:=True, ApplyToMembers:=True)> Friend Class Var
    Private m_name As String = ""
    Private m_description As BikDescription = Nothing

    Private m_address As Integer = 0
    Private m_multiplier As Double = 1
    Private m_offset As Double = 0
    Private m_importable As Boolean = False

    Private m_bitSize As Byte = 8
    Private m_bit As Byte = 0
    Private m_next As Var = Nothing
    <OptionalField(VersionAdded:=2)> _
    Private m_Mask As UInt16 = &HFFFF
    <NonSerialized()> Friend b_reloadMenu As Boolean = False
    <NonSerialized()> Private m_Values() As States.comboBoxItem

    <OptionalField(VersionAdded:=2)> _
    Private m_BitInvert As Boolean = False

    <OnDeserialized()> _
    Private Sub OnDeserializing(ByVal context As StreamingContext)
        If m_Mask = 0 Then m_Mask = &HFFFF
    End Sub

    Friend Sub New(ByVal Type As BikSettings.TableTypes, ByVal Address As UInt16)
        Me.New("Type", New BikDescription("Table Type Variable"), Address)
        b_reloadMenu = True
        If Type = BikSettings.TableTypes.BCTT_ONOFF Then
            SelectionValues = New States.comboBoxItem() _
               {New States.comboBoxItem("Unconfigured", &HFF), _
                New States.comboBoxItem("On/Off", &H3), _
                New States.comboBoxItem("Map Change", &H4) _
            }
        Else
            SelectionValues = New States.comboBoxItem() _
               {New States.comboBoxItem("Unconfigured", &HFF), _
                New States.comboBoxItem("Base Value", &H2), _
                New States.comboBoxItem("Trim %", &H0), _
                New States.comboBoxItem("Trim Val", &H1), _
                New States.comboBoxItem("On/Off", &H3) _
            }
        End If
    End Sub
    Friend Sub New(ByVal Variable As BikSettings.TableVariables, ByVal Address As UInt16)
        Me.New("Variable", New BikDescription("Variable This table uses"), Address)
        b_reloadMenu = True
        SelectionValues = New States.comboBoxItem() { _
            New States.comboBoxItem("NC", &HFF), _
            New States.comboBoxItem("RPM", 0), _
            New States.comboBoxItem("AFM", 1), _
            New States.comboBoxItem("TPS", 2), _
            New States.comboBoxItem("TEMP", 4), _
            New States.comboBoxItem("SPEED", 5), _
            New States.comboBoxItem("BK sw1", &H20), _
            New States.comboBoxItem("BK sw2", &H21), _
            New States.comboBoxItem("BK sw3", &H22), _
            New States.comboBoxItem("BK sw4", &H23), _
            New States.comboBoxItem("BK sw5", &H24), _
            New States.comboBoxItem("BKAD1", &H25), _
            New States.comboBoxItem("BKAD2", &H26), _
            New States.comboBoxItem("BKAD3", &H27), _
            New States.comboBoxItem("BKADLU1", &H60), _
            New States.comboBoxItem("BKADLU2", &H61), _
            New States.comboBoxItem("BKADLU3", &H62), _
            New States.comboBoxItem("TRIG 1", &H30), _
            New States.comboBoxItem("TRIG 2", &H31), _
            New States.comboBoxItem("TRIG 3", &H32), _
            New States.comboBoxItem("TRIG 4", &H33), _
            New States.comboBoxItem("TRIG 5", &H34), _
            New States.comboBoxItem("TRIG 6", &H35), _
            New States.comboBoxItem("TRIG 7", &H36), _
            New States.comboBoxItem("TRIG 8", &H37), _
            New States.comboBoxItem("TRIG 9", &H38), _
            New States.comboBoxItem("TRIG 10", &H39), _
            New States.comboBoxItem("TRIG 11", &H3A), _
            New States.comboBoxItem("TRIG 12", &H3B), _
            New States.comboBoxItem("TRIG 13", &H3C), _
            New States.comboBoxItem("TRIG 14", &H3D), _
            New States.comboBoxItem("TRIG 15", &H3E), _
            New States.comboBoxItem("TRIG 16", &H3F), _
            New States.comboBoxItem("TRIG 17", &H40), _
            New States.comboBoxItem("TRIG 18", &H41), _
            New States.comboBoxItem("TRIG 19", &H42), _
            New States.comboBoxItem("TRIG 20", &H43) _
        }
    End Sub
    Friend Sub New(ByVal Name_ As String, ByVal Desc_ As BikDescription, Optional ByVal Address_ As Integer = -1, Optional ByVal Multi_ As Double = 1, Optional ByVal BitSize As Byte = 8, Optional ByVal Mask As UInt16 = &HFFFF, Optional ByVal Offset As Double = 0)
        m_name = Trim(Name_)
        m_description = Desc_
        m_address = Address_
        m_multiplier = Multi_
        m_offset = Offset
        m_bitSize = BitSize
        m_Mask = Mask
    End Sub
    'Friend Sub New(ByVal Name_ As String, ByVal Desc_ As BikDescription, ByVal Address_ As Integer, ByVal Multi_ As Double, ByVal BitSize As Byte, ByVal Offset As Integer)
    '    Me.New(Name_, Desc_, Address_, Multi_, BitSize)
    '    Me.Offset = Offset
    'End Sub
    'Friend Sub New(ByVal Name_ As String, ByVal Desc_ As BikDescription, ByVal Address_ As Integer, ByVal Multi_ As Double, ByVal BitSize As Byte, ByVal Bit As Byte)
    '    m_name = Trim(Name_)
    '    m_description = Desc_
    '    m_address = Address_
    '    m_multiplier = Multi_
    '    m_bit = Bit
    '    If BitSize >= 1 And BitSize <= 16 Then
    '        m_bitSize = BitSize
    '    End If
    'End Sub
    'Friend Sub New(ByVal Name_ As String, ByVal Desc_ As BikDescription, ByVal Address_ As Integer, ByVal Multi_ As Double, ByVal BitSize As Byte, ByVal Offset As Integer, ByVal Bit As Byte)
    '    Me.New(Name_, Desc_, Address_, Multi_, BitSize)
    '    Me.Offset = Offset
    '    m_bit = Bit
    'End Sub
    Friend Sub New(ByVal Name_ As String, ByVal Desc_ As BikDescription, ByVal Address_ As Integer, ByVal Multi_ As Double, ByVal BitSize As Byte, ByVal Offset As Integer, ByVal Bit As Byte, ByVal Invert As Boolean)
        m_name = Trim(Name_)
        m_description = Desc_
        m_address = Address_
        m_multiplier = Multi_
        m_bit = Bit
        m_bitSize = BitSize
        Me.Offset = Offset
        Me.m_BitInvert = Invert
    End Sub
    Friend Sub addNode(ByRef node As Var)
        If IsNothing(m_next) Then
            If Trim(LCase(node.Name())) <> Trim(LCase(m_name)) Then
                m_next = node
            End If
        Else
            If Trim(LCase(node.Name())) <> Trim(LCase(m_name)) Then
                m_next.addNode(node)
            End If
        End If
    End Sub

    Public Property Name() As String
        Get
            Return m_name
        End Get
        Set(ByVal value As String)
            m_name = value
        End Set
    End Property
    Public Property Description() As BikDescription
        Get
            Return m_description
        End Get
        Set(ByVal value As BikDescription)
            m_description = value
        End Set
    End Property
    Public Property Address() As Integer
        Get
            Return m_address
        End Get
        Set(ByVal value As Integer)
            m_address = value
        End Set
    End Property
    Public Property Multiplier() As Double
        Get
            Return m_multiplier
        End Get
        Set(ByVal value As Double)
            m_multiplier = value
        End Set
    End Property
    Public Property Offset() As Double
        Get
            Return m_offset
        End Get
        Set(ByVal value As Double)
            m_offset = value
        End Set
    End Property
    Public Property Bit() As Byte
        Get
            Return m_bit
        End Get
        Set(ByVal value As Byte)
            m_bit = value
        End Set
    End Property
    Public Property Importable() As Boolean
        Get
            Return m_importable
        End Get
        Set(ByVal value As Boolean)
            m_importable = value
        End Set
    End Property
    Public Property BitSize() As Byte
        Get
            Return m_bitSize
        End Get
        Set(ByVal value As Byte)
            m_bitSize = value
        End Set
    End Property
    Public Property BitInvert() As Boolean
        Get
            Return m_BitInvert
        End Get
        Set(ByVal value As Boolean)
            m_BitInvert = value
        End Set
    End Property
    Public Property SelectionValues() As States.comboBoxItem()
        Get
            Return m_Values
        End Get
        Set(ByVal value As States.comboBoxItem())
            m_Values = value
        End Set
    End Property

    Friend Sub setNext(ByRef nextNode As Var)
        m_next = nextNode
    End Sub
    Friend Function getnext() As Var
        Return m_next
    End Function
    Friend Function lengthTotal() As Integer
        Dim intReturn As Integer
        intReturn = CInt(length())
        If (Not IsNothing(m_next)) Then
            intReturn = intReturn + m_next.lengthTotal
        End If
        Return (intReturn)
    End Function
    Friend Function count() As Integer
        Dim intReturn As Integer
        intReturn = 1
        If (Not IsNothing(m_next)) Then
            intReturn += m_next.count
        End If
        Return (intReturn)
    End Function

    Friend Sub SetValue(ByRef Array() As Byte, ByVal Value As Object)
        If Me.BitSize <> 0 Then
            Value = CSng(Val(Value))
            Value -= m_offset
            Value = Value / m_multiplier
            Dim f_Value As UInt16 = Value And m_Mask
            If Not IsNothing(Array) AndAlso UBound(Array) + 2 >= m_address + length() Then
                If length() = 2 Then
                    Array(m_address) = (Array(m_address) And ((m_Mask \ &H100) Xor &HFF)) Or HIBYTE(iShort(CLng(Value)))
                    Array(m_address + 1) = (Array(m_address + 1) And (m_Mask Xor &HFF)) Or LOBYTE(iShort(CLng(Value)))
                ElseIf m_bitSize = 1 Then
                    If Me.m_BitInvert And Value > 0 Then
                        Value = 0
                    ElseIf m_BitInvert And Value = 0 Then
                        Value = 1
                    End If
                    If Value > 0 Then
                        BitSet_byte(Array(m_address), m_bit)
                    Else
                        BitClear_byte(Array(m_address), m_bit)
                    End If
                ElseIf length() = 1 Then
                    Array(m_address) = (Array(m_address) And (m_Mask Xor &HFF)) Or iByte(CLng(Value))
                ElseIf length() = 4 Then
                    System.Array.Copy(System.BitConverter.GetBytes(CSng(Value)), 0, Array, m_address, 4)
                End If
            End If
        ElseIf Value.GetType Is GetType(String) Then ' String type! Oh YE! 8 char limit tho
            Dim f_arr(7) As Byte

            If CType(Value, String).Length >= 8 Then
                System.Array.Copy(cv_BytesFromString(CType(Value, String)), 0, f_arr, 0, 8)
            Else
                System.Array.Copy(cv_BytesFromString(CType(Value, String)), 0, f_arr, 0, CType(Value, String).Length)
            End If
            System.Array.Copy(f_arr, 0, Array, m_address, 8)
        End If
    End Sub
    Private Function length() As Integer
        If m_bitSize >= 1 And m_bitSize <= 8 Then
            Return 1
        ElseIf m_bitSize <= 16 Then
            Return 2
        ElseIf m_bitSize = 32 Then
            Return 4
        End If
    End Function
    Friend Sub setBytes(ByRef Array_() As Byte, ByVal Value_() As Byte)
        If UBound(Array_) + 2 >= m_address + length() And UBound(Value_) + 1 = length() Then
            If m_bitSize = 1 Then
                If BitIsSet_byte(Value_(0), m_bit) Then
                    BitSet_byte(Array_(m_address), m_bit)
                Else
                    BitClear_byte(Array_(m_address), m_bit)
                End If
            ElseIf length() = 1 Then
                Array_(m_address) = Value_(0)
            ElseIf length() = 2 Then
                Array_(m_address) = Value_(0)
                Array_(m_address + 1) = Value_(1)
            End If
        End If
    End Sub

    Friend Function getByte(ByRef array_() As Byte) As UInt32
        Dim f_value As Integer = 0
        If UBound(array_) + 2 >= m_address + length() Then
            If m_bitSize = 1 Then
                If BitIsSet_byte(array_(m_address), m_bit) Then
                    BitSett(f_value, m_bit)
                End If
            ElseIf length() = 1 Then
                f_value = array_(m_address)
            ElseIf length() = 2 Then
                f_value = MAKEWORD(array_(m_address + 1), array_(m_address))
            ElseIf length() = 4 Then
                f_value = makeLong(array_(m_address), array_(m_address + 1), array_(m_address + 2), array_(m_address + 3))
            End If
        End If
        Return f_value
    End Function
    Friend Function getBytes(ByRef array_() As Byte) As Byte()
        Dim f_value(0 To length() - 1) As Byte
        If UBound(array_) + 2 >= m_address + length() Then
            Array.Copy(array_, m_address, f_value, 0, length)
        End If
        Return f_value
    End Function
    Friend Function getValue(ByRef Array_() As Byte) As Object
        If Me.BitSize <> 0 Then
            Dim f_value As Single = 0
            If UBound(Array_) + 2 >= m_address + length() Then
                If m_bitSize = 1 Then
                    If Me.m_BitInvert Then
                        If Not BitIsSet_byte(Array_(m_address), m_bit) Then f_value = 1
                    Else
                        If BitIsSet_byte(Array_(m_address), m_bit) Then f_value = 1
                    End If
                ElseIf length() = 1 Then
                    f_value = ((Array_(m_address) And m_Mask) * m_multiplier) + m_offset
                ElseIf length() = 2 Then
                    f_value = ((MAKEWORD(Array_(m_address + 1), Array_(m_address)) And m_Mask) * m_multiplier) + m_offset
                ElseIf length() = 4 Then
                    f_value = (System.BitConverter.ToSingle(Array_, m_address) * m_multiplier) + m_offset
                End If
            End If
            Return f_value
        Else
            Dim f_value As String = cv_StringFromBytes(Array_, m_address, 8)
            Return f_value
        End If
    End Function
End Class
